/*
 * Copyright 2012 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudgettable.client.ui.grid.column;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import finbudgettable.client.ui.grid.Resizable;
import finbudgettable.client.ui.grid.cell.BrowserEventListener;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ResizeHelper<C> implements BrowserEventListener<C> {

    public static interface PositionController {
        int getPosition(Event event);
    }

    public static class HorizontalPositionController implements PositionController {

        @Override
        public int getPosition(Event event) {
            return event.getClientX() + Document.get().getScrollLeft();
        }
    }

    private final Resizable cell;
    private final PositionController positionController;
    private int startPosition;
    private int startSize;
    com.google.gwt.user.client.Element resizer;

    private final Set<String> consumedEvents = new HashSet<String>(Arrays.asList(BrowserEvents.MOUSEDOWN));

    public ResizeHelper(Resizable cell, PositionController positionController) {
        this.cell = cell;
        this.positionController = positionController;
    }

    private final EventListener eventListener = new EventListener() {
        @Override
        public void onBrowserEvent(Event event) {
            String eventType = event.getType();
            if (BrowserEvents.MOUSEMOVE.equals(eventType)) {
                int currentPosition = positionController.getPosition(event);
                cell.setSize(startSize + currentPosition - startPosition);
            } else if (BrowserEvents.MOUSEUP.equals(eventType)) {
                DOM.releaseCapture(resizer);
                DOM.setEventListener(resizer, null);
            }
        }
    };

    @Override
    public boolean onBrowserEvent(Cell.Context context, Element parent, C value, NativeEvent event, ValueUpdater<C> cValueUpdater) {
        resizer = cell.getResizeElement().cast();
        if (event.getEventTarget().equals(resizer)) {
            String eventType = event.getType();
            if (BrowserEvents.MOUSEDOWN.equals(eventType)) {
                startPosition = positionController.getPosition(Event.getCurrentEvent());
                int events = Event.getTypeInt(BrowserEvents.MOUSEMOVE) | Event.getTypeInt(BrowserEvents.MOUSEUP);
                DOM.setEventListener(resizer, eventListener);
                DOM.sinkEvents(resizer, events);
                DOM.setCapture(resizer);
                startSize = cell.getSize(parent);
                event.preventDefault();
                return true;
            }
        }
        return false;
    }

    @Override
    public Set<String> getConsumedEvents() {
        return consumedEvents;
    }
}
